package com.ruoyi.quartz.task;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.common.enums.AmountType;
import com.ruoyi.common.utils.AESUtil;
import com.ruoyi.common.utils.BigDecimalUtil;
import com.ruoyi.common.utils.Web3Utils;
import com.ruoyi.system.domain.WdyUser;
import com.ruoyi.system.domain.WdyWalletCollect;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.IWdyUserService;
import com.ruoyi.system.service.IWdyWalletCollectService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.WalletUtils;
import org.web3j.tx.gas.DefaultGasProvider;
import org.web3j.utils.Convert;

import java.io.File;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;

@Component("walletTask")
public class WalletTask {
    protected Logger log = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private IWdyUserService wdyUserService;

    @Autowired
    private ISysConfigService sysConfigService;

    @Autowired
    private IWdyWalletCollectService wdyWalletCollectService;

    @Value("${wallet.contract.usdt}")
    private String usdtContract;

    public void createWallet() {
        QueryWrapper<WdyUser> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("wallet_address", "");
        List<WdyUser> list = wdyUserService.list(userQueryWrapper);
        if(!CollectionUtils.isEmpty(list)) {
            list.forEach(wdyUser -> {
                try {
                    WdyUser updateUser = new WdyUser();
                    updateUser.setId(wdyUser.getId());
                    File dir = new File((System.getProperty("os.name").toLowerCase().startsWith("win") ? "D:" : "") + WdyUser.WALLET_DIR);
                    if(!dir.exists()) {
                        dir.mkdirs();
                    }
                    String walletFileName = WalletUtils.generateFullNewWalletFile(WdyUser.WALLET_PWD, dir);
                    String source = dir.getAbsolutePath() + "/" + walletFileName;
                    Credentials credentials = WalletUtils.loadCredentials(WdyUser.WALLET_PWD, source);
                    updateUser.setWalletAddress(credentials.getAddress());
                    updateUser.setWalletPrivateKey(AESUtil.encrypt(credentials.getEcKeyPair().getPrivateKey().toString(16)));
                    wdyUserService.updateById(updateUser);
                } catch (Exception e) {
                    log.error("生成钱包异常", e);
                }
            });
        }
    }

    public void collect() {
        QueryWrapper<WdyUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("user_id", "wallet_address", "wallet_private_key");
        List<WdyUser> list = wdyUserService.list(queryWrapper);
        if(list != null && !list.isEmpty()) {
            String companyWalletAddress = sysConfigService.selectConfigByKey("company_wallet_address");
            for (WdyUser user : list) {
                try {
                    String privateKey = AESUtil.decrypt(user.getWalletPrivateKey());
                    BigDecimal ethBalance = new BigDecimal(Web3Utils.queryAccountAmount(user.getWalletAddress()));
                    BigDecimal gasLimit = new BigDecimal(21000);
                    BigDecimal transferFee = BigDecimalUtil.multiply(new BigDecimal(DefaultGasProvider.GAS_PRICE), gasLimit);
                    if(ethBalance.compareTo(transferFee) > 0) {
                        BigInteger usdtBalance = Web3Utils.balanceOf(user.getWalletAddress(), usdtContract);
                        if(usdtBalance.compareTo(BigInteger.ZERO) > 0) {
                            Credentials credentials = Credentials.create(privateKey);
                            String usdtTxnHash = Web3Utils.transfer(credentials, companyWalletAddress, usdtBalance, usdtContract, DefaultGasProvider.GAS_PRICE, gasLimit.toBigInteger());
                            WdyWalletCollect entity = new WdyWalletCollect();
                            entity.setUserId(user.getUserId());
                            entity.setTxnHash(usdtTxnHash);
                            entity.setAmount(new BigDecimal(usdtBalance).divide(new BigDecimal(1000000), 6, BigDecimal.ROUND_DOWN));
                            entity.setAmountType(AmountType.USDT.getCode());
                            wdyWalletCollectService.save(entity);
                            ethBalance = ethBalance.subtract(transferFee);
                        }
                        if(ethBalance.compareTo(transferFee) > 0) {
                            BigDecimal transferAmount = ethBalance.subtract(transferFee);
                            String ethTxnHash = Web3Utils.transfer(companyWalletAddress, transferAmount, Convert.Unit.WEI, privateKey);
                            WdyWalletCollect entity = new WdyWalletCollect();
                            entity.setUserId(user.getUserId());
                            entity.setTxnHash(ethTxnHash);
                            entity.setAmount(Convert.fromWei(transferAmount, Convert.Unit.ETHER));
                            entity.setAmountType(AmountType.ETH.getCode());
                            wdyWalletCollectService.save(entity);
                        }
                    }
                } catch (Exception e) {
                    log.error("钱包汇总异常", e);
                }

            }
        }
    }
}
